import 'dart:convert';
import 'dart:io';

import 'package:archive/archive_io.dart';
import 'package:fast_gbk/fast_gbk.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_widgets_pc/extentions/kq_extentions.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';

import 'dialog_util.dart';

/// 文件操作工具类
class FileUtil {
  /// 获取 C:\Users\你的用户名\AppData\Roaming\ 目录
  static Future<String> getRoamingDirectory() async {
    final directory = await getApplicationSupportDirectory();
    var path = directory.path;
    if (!path.endsWith(separator())) {
      return '$path${separator()}';
    }
    return path;
  }

  /// 获取临时缓存目录
  static Future<String> getTempDirPath() async {
    var path = (await getTemporaryDirectory()).path;
    if (!path.endsWith(separator())) {
      return '$path${separator()}';
    }
    return path;
  }

  /// 获取临时下载目录
  static Future<String> getTempDownloadPath() async {
    var tempPath = await getTempDirPath();
    var downloadDir = '${tempPath}Download${separator()}';
    await mkDirs(downloadDir);
    return downloadDir;
  }

  /// 创建文件夹
  static Future mkDirs(String dirPath) async {
    Directory dir = Directory(dirPath);
    try {
      bool exists = await dir.exists();
      if (!exists) {
        await dir.create(recursive: true);
      }
    } catch (e) {
      if (kDebugMode) {
        print(e);
      }
    }
  }

  /// 清理下载目录
  static Future clearDownloadCache() async {
    var path = await getTempDownloadPath();
    File file = File(path);
    await file.delete(recursive: true);
  }

  /// 清理指定目录
  static Future deleteDir(String dirPath, {bool recursive = true}) async {
    File file = File(dirPath);
    await file.delete(recursive: recursive);
  }

  /// 读取文件成字符串
  static Future<String> readFileAsString(String filePath,
      {Encoding encoding = utf8}) async {
    var file = File(filePath);
    if (file.existsSync()) {
      return file.readAsStringSync(encoding: encoding);
    }
    return '';
  }

  /// 读取文件成字符串，自动获取编码，目前仅支持（gbk和utf-8）
  static Future<String> readFileAsStringAutoEncoding(String filePath) async {
    var file = File(filePath);
    if (file.existsSync()) {
      var bytes = await file.readAsBytes();
      var encoding = detectEncoding(bytes);
      return encoding.decode(bytes);
    }
    return '';
  }

  /// 文件分隔符
  static String separator() {
    return Platform.isWindows ? "\\" : "/";
  }

  /// 文件夹是否有文件
  static Future<bool> hasChildFile(String dirPath) async {
    Directory dir = Directory(dirPath);
    if (dir.existsSync()) {
      var listSync = dir.listSync();
      return listSync.isNotEmpty;
    }
    return false;
  }

  static Encoding detectEncoding(Uint8List bytes) {
    // 尝试使用常见的编码进行解码
    List<Encoding> encodingsToTry = [
      utf8,
      gbk,
    ];

    for (var encoding in encodingsToTry) {
      try {
        // 解码文本，如果成功则返回此编码
        encoding.decode(bytes);
        return encoding;
      } catch (_) {
        continue;
      }
    }

    // 如果无法确定编码，返回默认编码
    return utf8;
  }

  /// 解压assets目录的zip文件
  static Future unZipAssetsFile(
      String bundleZipPath, String fileName, String unZipDirPath) async {
    var data = await rootBundle.load(bundleZipPath);
    List<int> bytes =
        data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
    var downloadPath = await FileUtil.getTempDownloadPath();
    var newPath = '$downloadPath$fileName';
    File file = File(newPath);
    //zip文件先存到文件系统
    await file.writeAsBytes(bytes);
    //然后解压
    await extractZipFile(newPath, unZipDirPath);
  }

  /// 文件是否存在
  static bool existFile(String filePath) {
    File file = File(filePath);
    return file.existsSync();
  }

  /// 文件夹是否存在
  static bool existDir(String dirPath) {
    Directory file = Directory(dirPath);
    return file.existsSync();
  }

  static void closeFile(File file) {
    if (file.existsSync()) {
      final openedFile = file.openSync(mode: FileMode.read);
      openedFile.closeSync();
    }
  }

  static Future<void> extractZipFile(
      String zipFilePath, String extractPath) async {
    final bytes = await File(zipFilePath).readAsBytes();
    final archive = ZipDecoder().decodeBytes(bytes);
    await Directory(extractPath).create(recursive: true);
    for (final file in archive) {
      final filePath = '$extractPath${separator()}${file.name}';
      if (file.isFile) {
        final outFile = File(filePath)..createSync(recursive: true);
        outFile.writeAsBytesSync(file.content);
        closeFile(outFile);
      } else {
        Directory(filePath).createSync(recursive: true);
      }
    }
  }

  /// 文件大小格式化
  static String formatBytes(int bytes, {int decimals = 2}) {
    if (bytes <= 0) {
      return "0 B";
    }
    final suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
    var i = 0;
    var size = bytes.toDouble();
    while (size >= 1024) {
      size /= 1024;
      i++;
    }
    return "${size.toStringAsFixed(decimals)} ${suffixes[i]}";
  }

  /// 保存字节数组成文件
  static Future<String> saveBytesToFile(
      List<int> bytes, String filePath) async {
    final file = File(filePath);
    await file.writeAsBytes(bytes);
    return filePath;
  }

  /// 打开文件/文件夹
  /// [openDir] 打开文件时是否打开文件夹，默认true
  static openInFinder(String filePath, {bool openDir = true}) async {
    KqDialog.showLoading();
    bool isFile = await FileSystemEntity.isFile(filePath);
    if (isFile && openDir) {
      File file = File(filePath);
      var parent = file.parentPath;
      await OpenFile.open(parent);
    }
    await OpenFile.open(filePath);
    KqDialog.closeLoading();
  }
}

extension ListUtil<T> on List<T> {
  /// 将列表倒序
  List<T> reverseList() {
    List<T> newList = [];
    for (int i = length - 1; i >= 0; i--) {
      newList.add(this[i]);
    }
    return newList;
  }
}
